home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1997 January / Macworld (1997-01).dmg / Shareware World / Fonts / Metafont / Inputs / plain.mf < prev    next >
Text File  |  1996-06-04  |  23KB  |  590 lines

  1. % This is the plain METAFONT base that's described in The METAFONTbook.
  2. % N.B.: Please change "base_version" whenever this file is modified!
  3. % And don't modify the file under any circumstances.
  4. string base_name, base_version; base_name="plain"; base_version="2.71";
  5.  
  6. message "Preloading the plain base, version "&base_version&": preliminaries,";
  7.  
  8. delimiters ();  % this makes parentheses behave like parentheses
  9. def upto = step 1 until enddef; % syntactic sugar
  10. def downto = step -1 until enddef;
  11. def exitunless expr c = exitif not c enddef;
  12. let relax = \;  % ignore the word `relax', as in TeX
  13. let \\ = \; % double relaxation is like single
  14. def ]] = ] ] enddef; % right brackets should be loners
  15. def -- = {curl 1}..{curl 1} enddef;
  16. def --- = .. tension infinity .. enddef;
  17. def ... = .. tension atleast 1 .. enddef;
  18.  
  19. def gobble primary g = enddef; def killtext text t = enddef;
  20. primarydef g gobbled gg = enddef;
  21. def hide(text t) = exitif numeric begingroup t;endgroup; enddef;
  22. def ??? = hide(interim showstopping:=1; showdependencies) enddef;
  23. def stop expr s = message s; gobble readstring enddef;
  24.  
  25. smoothing:=1; autorounding:=2;  % this adjusts curves to the raster
  26. turningcheck:=2;                % this will warn about a "strange path"
  27. granularity:=1;                 % this says that pixels are pixels
  28.  
  29. def interact = % sets up to make "show" commands stop
  30.  hide(showstopping:=1; tracingonline:=1) enddef;
  31.  
  32. def loggingall =        % puts tracing info into the log
  33.  tracingcommands:=3; tracingedges:=2; tracingtitles:=1; tracingequations:=1;
  34.  tracingcapsules:=1; tracingspecs:=1; tracingpens:=1; tracingchoices:=1;
  35.  tracingstats:=1; tracingoutput:=1; tracingmacros:=1; tracingrestores:=1;
  36.  enddef;
  37.  
  38. def tracingall =        % turns on every form of tracing
  39.  tracingonline:=1; showstopping:=1; loggingall enddef;
  40.  
  41. def tracingnone =       % turns off every form of tracing
  42.  tracingcommands:=0; tracingonline:=0; showstopping:=0;
  43.  tracingedges:=0; tracingtitles:=0; tracingequations:=0;
  44.  tracingcapsules:=0; tracingspecs:=0; tracingpens:=0; tracingchoices:=0;
  45.  tracingstats:=0; tracingoutput:=0; tracingmacros:=0; tracingrestores:=0;
  46.  enddef;
  47.  
  48. message " basic constants and mathematical macros,";
  49.  
  50. % numeric constants
  51. newinternal eps,epsilon,infinity,_;
  52. eps := .00049;    % this is a pretty small positive number
  53. epsilon := 1/256/256;   % but this is the smallest
  54. infinity := 4095.99998;    % and this is the largest
  55. _ := -1; % internal constant to make macros unreadable but shorter
  56.  
  57. % pair constants
  58. pair right,left,up,down,origin;
  59. origin=(0,0); up=-down=(0,1); right=-left=(1,0);
  60.  
  61. % path constants
  62. path quartercircle,halfcircle,fullcircle,unitsquare;
  63. quartercircle=(right{up}..(right+up)/sqrt2..up{left}) scaled .5;
  64. halfcircle=quartercircle & quartercircle rotated 90;
  65. fullcircle=halfcircle & halfcircle rotated 180 & cycle;
  66. unitsquare=(0,0)--(1,0)--(1,1)--(0,1)--cycle;
  67.  
  68. % transform constants
  69. transform identity;
  70. for z=origin,right,up: z transformed identity = z; endfor
  71.  
  72. % picture constants
  73. picture blankpicture,unitpixel;
  74. blankpicture=nullpicture; % `display blankpicture...'
  75. unitpixel=nullpicture; addto unitpixel contour unitsquare;
  76.  
  77. % string constants
  78. string ditto; ditto = char 34; % ASCII double-quote mark
  79.  
  80. % pen constants
  81. def capsule_def(suffix s) primary u = def s = u enddef enddef;
  82. capsule_def(pensquare) makepen(unitsquare shifted -(.5,.5));
  83. capsule_def(penrazor) makepen((-.5,0)--(.5,0)--cycle);
  84. pen penspeck; penspeck=pensquare scaled eps;
  85.  
  86. % nullary operators
  87. vardef whatever = save ?; ? enddef;
  88.  
  89. % unary operators
  90. let abs = length;
  91.  
  92. vardef round primary u =
  93.  if numeric u: floor(u+.5)
  94.  elseif pair u: (hround xpart u, vround ypart u)
  95.  else: u fi enddef;
  96.  
  97. vardef hround primary x = floor(x+.5) enddef;
  98. vardef vround primary y = floor(y.o_+.5)_o_ enddef;
  99.  
  100. vardef ceiling primary x = -floor(-x) enddef;
  101.  
  102. vardef byte primary s =
  103.  if string s: ASCII fi s enddef;
  104.  
  105. vardef dir primary d = right rotated d enddef;
  106.  
  107. vardef unitvector primary z = z/abs z enddef;
  108.  
  109. vardef inverse primary T =
  110.  transform T_; T_ transformed T = identity; T_ enddef;
  111.  
  112. vardef counterclockwise primary c =
  113.  if turningcheck>0:
  114.   interim autorounding:=0;
  115.   if turningnumber c <= 0: reverse fi fi c enddef;
  116.  
  117. vardef tensepath expr r =
  118.  for k=0 upto length r - 1: point k of r --- endfor
  119.  if cycle r: cycle else: point infinity of r fi enddef;
  120.  
  121. % binary operators
  122.  
  123. primarydef x mod y = (x-y*floor(x/y)) enddef;
  124. primarydef x div y = floor(x/y) enddef;
  125. primarydef w dotprod z = (xpart w * xpart z + ypart w * ypart z) enddef;
  126.  
  127. primarydef x**y = if y=2: x*x else: takepower y of x fi enddef;
  128. def takepower expr y of x =
  129.  if x>0: mexp(y*mlog x)
  130.  elseif (x=0) and (y>0): 0
  131.  else: 1
  132.   if y=floor y:
  133.    if y>=0: for n=1 upto y: *x endfor
  134.    else: for n=_ downto y: /x endfor
  135.    fi
  136.   else: hide(errmessage "Undefined power: " & decimal x&"**"&decimal y)
  137.   fi fi enddef;
  138.  
  139. vardef direction expr t of p =
  140.  postcontrol t of p - precontrol t of p enddef;
  141.  
  142. vardef directionpoint expr z of p =
  143.  a_:=directiontime z of p;
  144.  if a_<0: errmessage("The direction doesn't occur"); fi
  145.  point a_ of p enddef;
  146.  
  147. secondarydef p intersectionpoint q =
  148.  begingroup save x_,y_; (x_,y_)=p intersectiontimes q;
  149.  if x_<0: errmessage("The paths don't intersect"); origin
  150.  else: .5[point x_ of p, point y_ of q] fi endgroup
  151. enddef;
  152.  
  153. tertiarydef p softjoin q =
  154.  begingroup c_:=fullcircle scaled 2join_radius shifted point 0 of q;
  155.  a_:=ypart(c_ intersectiontimes p); b_:=ypart(c_ intersectiontimes q);
  156.  if a_<0:point 0 of p{direction 0 of p} else: subpath(0,a_) of p fi
  157.   ... if b_<0:{direction infinity of q}point infinity of q
  158.    else: subpath(b_,infinity) of q fi endgroup enddef;
  159. newinternal join_radius,a_,b_; path c_;
  160.  
  161. % special operators
  162. vardef incr suffix $ = $:=$+1; $ enddef;
  163. vardef decr suffix $ = $:=$-1; $ enddef;
  164.  
  165. def reflectedabout(expr w,z) =    % reflects about the line w..z
  166.  transformed
  167.   begingroup transform T_;
  168.   w transformed T_ = w;  z transformed T_ = z;
  169.   xxpart T_ = -yypart T_; xypart T_ = yxpart T_; % T_ is a reflection
  170.   T_ endgroup enddef;
  171.  
  172. def rotatedaround(expr z, d) =    % rotates d degrees around z
  173.  shifted -z rotated d shifted z enddef;
  174. let rotatedabout = rotatedaround;   % for roundabout people
  175.  
  176. vardef min(expr u)(text t) = % t is a list of numerics, pairs, or strings
  177.  save u_; setu_ u; for uu = t: if uu<u_: u_:=uu; fi endfor
  178.  u_ enddef;
  179.  
  180. vardef max(expr u)(text t) = % t is a list of numerics, pairs, or strings
  181.  save u_; setu_ u; for uu = t: if uu>u_: u_:=uu; fi endfor
  182.  u_ enddef;
  183.  
  184. def setu_ primary u =
  185.  if pair u: pair u_ elseif string u: string u_ fi;
  186.  u_=u enddef;
  187.  
  188. def flex(text t) =           % t is a list of pairs
  189.  hide(n_:=0; for z=t: z_[incr n_]:=z; endfor
  190.   dz_:=z_[n_]-z_1)
  191.  z_1 for k=2 upto n_-1: ...z_[k]{dz_} endfor ...z_[n_] enddef;
  192. newinternal n_; pair z_[],dz_;
  193.  
  194. def superellipse(expr r,t,l,b,s)=
  195.  r{up}...(s[xpart t,xpart r],s[ypart r,ypart t]){t-r}...
  196.  t{left}...(s[xpart t,xpart l],s[ypart l,ypart t]){l-t}...
  197.  l{down}...(s[xpart b,xpart l],s[ypart l,ypart b]){b-l}...
  198.  b{right}...(s[xpart b,xpart r],s[ypart r,ypart b]){r-b}...cycle enddef;
  199.  
  200. vardef interpath(expr a,p,q) =
  201.  for t=0 upto length p-1: a[point t of p, point t of q]
  202.   ..controls a[postcontrol t of p, postcontrol t of q]
  203.    and a[precontrol t+1 of p, precontrol t+1 of q] .. endfor
  204.  if cycle p: cycle
  205.  else: a[point infinity of p, point infinity of q] fi enddef;
  206.  
  207. vardef solve@#(expr true_x,false_x)= % @#(true_x)=true, @#(false_x)=false
  208.  tx_:=true_x; fx_:=false_x;
  209.  forever: x_:=.5[tx_,fx_]; exitif abs(tx_-fx_)<=tolerance;
  210.  if @#(x_): tx_ else: fx_ fi :=x_; endfor
  211.  x_ enddef; % now x_ is near where @# changes from true to false
  212. newinternal tolerance, tx_,fx_,x_; tolerance:=.1;
  213.  
  214. message " macros for converting from device-independent units to pixels,";
  215.  
  216. def fix_units = % define the conversion factors, given pixels_per_inch
  217.  mm:=pixels_per_inch/25.4;      cm:=pixels_per_inch/2.54;
  218.  pt:=pixels_per_inch/72.27;     pc:=pixels_per_inch/6.0225;
  219.  dd:=1238/1157pt;               cc:=12dd;
  220.  bp:=pixels_per_inch/72;        in:=pixels_per_inch;
  221.  hppp:=pt;                      % horizontal pixels per point
  222.  vppp:=aspect_ratio*hppp;       % vertical pixels per point
  223.  enddef;
  224.  
  225. mm#=2.84528;      pt#=1;        dd#=1.07001;      bp#:=1.00375;
  226. cm#=28.45276;     pc#=12;       cc#=12.84010;     in#:=72.27;
  227.  
  228. newinternal pixels_per_inch;       % the given resolution
  229. newinternal blacker, o_correction; % device-oriented corrections
  230.  
  231. def define_pixels(text t) =
  232.  forsuffixes $=t: $:=$.#*hppp; endfor enddef;
  233. def define_whole_pixels(text t) =
  234.  forsuffixes $=t: $:=hround($.#*hppp); endfor enddef;
  235. def define_whole_vertical_pixels(text t) =
  236.  forsuffixes $=t: $:=vround($.#*hppp); endfor enddef;
  237. def define_good_x_pixels(text t) =
  238.  forsuffixes $=t: $:=good.x($.#*hppp); endfor enddef;
  239. def define_good_y_pixels(text t) =
  240.  forsuffixes $=t: $:=good.y($.#*hppp); endfor enddef;
  241. def define_blacker_pixels(text t) =
  242.  forsuffixes $=t: $:=$.#*hppp+blacker; endfor enddef;
  243. def define_whole_blacker_pixels(text t) =
  244.  forsuffixes $=t: $:=hround($.#*hppp+blacker);
  245.   if $<=0: $:=1; fi endfor enddef;
  246. def define_whole_vertical_blacker_pixels(text t) =
  247.  forsuffixes $=t: $:=vround($.#*hppp+blacker);
  248.   if $<=0: $:=1_o_; fi endfor enddef;
  249. def define_corrected_pixels(text t) =
  250.  forsuffixes $=t: $:=vround($.#*hppp*o_correction)+eps; endfor enddef;
  251. def define_horizontal_corrected_pixels(text t) =
  252.  forsuffixes $=t: $:=hround($.#*hppp*o_correction)+eps; endfor enddef;
  253.  
  254. def lowres_fix(text t) expr ratio =
  255.  begingroup save min,max,first;
  256.  forsuffixes $=t: if unknown min: min=max=first=$; min#=max#=$.#;
  257.   elseif $.#<min#: min:=$; min#:=$.#;
  258.   elseif $.#>max#: max:=$; max#:=$.#; fi endfor
  259.  if max/min>ratio*max#/min#: forsuffixes $=t: $:=first; endfor fi
  260.  endgroup enddef;
  261.  
  262. message " macros and tables for various modes of operation,";
  263.  
  264. def mode_setup =
  265.  warningcheck:=0;
  266.  if unknown mode: mode=proof; fi
  267.  numeric aspect_ratio; transform currenttransform;
  268.  scantokens if string mode:("input "&mode) else: mode_name[mode] fi;
  269.  if unknown mag: mag=1; fi
  270.  if unknown aspect_ratio: aspect_ratio=1; fi
  271.  displaying:=proofing;
  272.  pixels_per_inch:=pixels_per_inch*mag;
  273.  if aspect_ratio=1: let o_=\; let _o_=\
  274.  else: def o_=*aspect_ratio enddef; def _o_=/aspect_ratio enddef fi;
  275.  fix_units;
  276.  scantokens extra_setup; % the user's special last-minute adjustments
  277.  currenttransform:=
  278.   if unknown currenttransform: identity else: currenttransform fi
  279.    yscaled aspect_ratio;
  280.  clearit;
  281.  pickup pencircle scaled (.4pt+blacker);
  282.  warningcheck:=1; enddef;
  283. def smode = string mode; mode enddef;
  284. string extra_setup, mode_name[];
  285. extra_setup="";          % usually there's nothing special to do
  286. newinternal displaying;  % if positive, endchar will `showit'
  287.  
  288. vardef magstep primary m = mexp(46.67432m) enddef;
  289.  
  290. def mode_def suffix $ =
  291.  $:=incr number_of_modes;
  292.  mode_name[$]:=str$ & "_";
  293.  expandafter quote def scantokens mode_name[$] enddef;
  294. newinternal number_of_modes;
  295.  
  296. % proof mode: for initial design of characters
  297. mode_def proof =
  298.  proofing:=2;                   % yes, we're making full proofs
  299.  fontmaking:=0;                 % no, we're not making a font
  300.  tracingtitles:=1;              % yes, show titles online
  301.  pixels_per_inch:=2601.72;      % that's 36 pixels per pt
  302.  blacker:=0;                    % no additional blackness
  303.  fillin:=0;                     % no compensation for fillin
  304.  o_correction:=1;               % no reduction in overshoot
  305.  enddef;
  306.  
  307. % smoke mode: for label-free proofs to mount on the wall
  308. mode_def smoke =
  309.  proof_;                        % same as proof mode, except:
  310.  proofing:=1;                   % yes, we're making unlabeled proofs
  311.  extra_setup:=extra_setup&"grayfont black"; % with solid black pixels
  312.  let makebox=maketicks;         % make the boxes less obtrusive
  313.  enddef;
  314.  
  315. % lowres mode: for certain devices that print 200 pixels per inch
  316. mode_def lowres =
  317.  proofing:=0;                   % no, we're not making proofs
  318.  fontmaking:=1;                 % yes, we are making a font
  319.  tracingtitles:=0;              % no, don't show titles at all
  320.  pixels_per_inch:=200;          % that's the meaning of lowres
  321.  blacker:=.65;                  % make pens a bit blacker
  322.  fillin:=.2;                    % compensate for diagonal fillin
  323.  o_correction:=.4;              % but don't overshoot as much
  324.  enddef;
  325.  
  326. localfont:=lowres;      % the mode most commonly used to make fonts
  327.  
  328. % It is customary to input another file to supplement the PLAIN base.
  329. % This supplementary file adds analogous modes, corresponding to
  330. % local output devices, and it redefines `localfont' as appropriate.
  331. % The values of screen_rows and screen_cols should also be updated.
  332. % The auxiliary file should set base_version:=base_version&"/localname".
  333. % Remember that the present file PLAIN.MF should not be changed;
  334. % all local changes should be confined to a separate file.
  335.  
  336. message " macros for drawing and filling,";
  337.  
  338. pen currentpen;
  339. path currentpen_path;
  340. picture currentpicture;
  341. transform currenttransform;
  342. def t_ = transformed currenttransform enddef;
  343.  
  344. def fill expr c = addto_currentpicture contour c.t_ enddef;
  345. def addto_currentpicture = addto currentpicture enddef;
  346. def draw expr p =
  347.  addto_currentpicture doublepath p.t_ withpen currentpen enddef;
  348. def filldraw expr c = fill counterclockwise c withpen currentpen enddef;
  349. def drawdot expr z = if unknown currentpen_path: def_pen_path_ fi
  350.  addto_currentpicture contour
  351.   currentpen_path shifted (z.t_) withpen penspeck enddef;
  352. def def_pen_path_ =
  353.  hide(currentpen_path=tensepath makepath currentpen) enddef;
  354.  
  355. def unfill expr c = fill c withweight _ enddef;
  356. def undraw expr p = draw p withweight _ enddef;
  357. def unfilldraw expr c = filldraw c withweight _ enddef;
  358. def undrawdot expr z = drawdot z withweight _ enddef;
  359. def erase text t = begingroup interim default_wt_:=_;
  360.  cullit; t withweight _; cullit; endgroup enddef;
  361. newinternal default_wt_; default_wt_:=1;
  362.  
  363. def cutdraw expr p = % caution: you may need autorounding=0
  364.  cutoff(point 0 of p, 180+angle direction 0 of p);
  365.  cutoff(point infinity of p, angle direction infinity of p);
  366.  culldraw p enddef;
  367. def culldraw expr p = addto pic_ doublepath p.t_ withpen currentpen;
  368.  cull pic_ dropping(-infinity,0) withweight default_wt_;
  369.  addto_currentpicture also pic_; pic_:=nullpicture; killtext enddef;
  370. vardef cutoff(expr z,theta) =
  371.  interim autorounding := 0; interim smoothing := 0;
  372.  addto pic_ doublepath z.t_ withpen currentpen;
  373.  addto pic_ contour
  374.   (cut_ scaled (1+max(-pen_lft,pen_rt,pen_top,-pen_bot))
  375.    rotated theta shifted z)t_;
  376.  cull pic_ keeping (2,2) withweight -default_wt_;
  377.  addto currentpicture also pic_;
  378.  pic_:=nullpicture enddef;
  379. picture pic_; pic_:=nullpicture;
  380. path cut_; cut_ = ((0,_)--(1,_)--(1,1)--(0,1)--cycle) scaled 1.42;
  381.  
  382. def pickup secondary q =
  383.  if numeric q: numeric_pickup_ else: pen_pickup_ fi q enddef;
  384. def numeric_pickup_ primary q =
  385.  if unknown pen_[q]: errmessage "Unknown pen"; clearpen
  386.  else: currentpen:=pen_[q];
  387.   pen_lft:=pen_lft_[q];
  388.   pen_rt:=pen_rt_[q];
  389.   pen_top:=pen_top_[q];
  390.   pen_bot:=pen_bot_[q];
  391.   currentpen_path:=pen_path_[q] fi; enddef;
  392. def pen_pickup_ primary q =
  393.   currentpen:=q yscaled aspect_ratio;
  394.   pen_lft:=xpart penoffset down of currentpen;
  395.   pen_rt:=xpart penoffset up of currentpen;
  396.   pen_top:=(ypart penoffset left of currentpen)_o_;
  397.   pen_bot:=(ypart penoffset right of currentpen)_o_;
  398.   path currentpen_path; enddef;
  399. newinternal pen_lft,pen_rt,pen_top,pen_bot,pen_count_;
  400.  
  401. vardef savepen = pen_[incr pen_count_]=currentpen;
  402.  pen_lft_[pen_count_]=pen_lft;
  403.  pen_rt_[pen_count_]=pen_rt;
  404.  pen_top_[pen_count_]=pen_top;
  405.  pen_bot_[pen_count_]=pen_bot;
  406.  pen_path_[pen_count_]=currentpen_path;
  407.  pen_count_ enddef;
  408.  
  409. def clearpen = currentpen:=nullpen;
  410.  pen_lft:=pen_rt:=pen_top:=pen_bot:=0;
  411.  path currentpen_path;
  412.  enddef;
  413. def clear_pen_memory =
  414.  pen_count_:=0;
  415.  numeric pen_lft_[],pen_rt_[],pen_top_[],pen_bot_[];
  416.  pen currentpen,pen_[];
  417.  path currentpen_path, pen_path_[];
  418.  enddef;
  419.  
  420. vardef lft primary x = x + if pair x: (pen_lft,0) else: pen_lft fi enddef;
  421. vardef rt primary x = x + if pair x: (pen_rt,0) else: pen_rt fi enddef;
  422. vardef top primary y = y + if pair y: (0,pen_top) else: pen_top fi enddef;
  423. vardef bot primary y = y + if pair y: (0,pen_bot) else: pen_bot fi enddef;
  424. vardef good.x primary x = hround(x+pen_lft)-pen_lft enddef;
  425. vardef good.y primary y = vround(y+pen_top)-pen_top enddef;
  426. vardef good.lft primary z = save z_; pair z_;
  427.   (z_+(pen_lft,0))t_=round((z+(pen_lft,0))t_); z_ enddef;
  428. vardef good.rt primary z = save z_; pair z_;
  429.   (z_+(pen_rt,0))t_=round((z+(pen_rt,0))t_); z_ enddef;
  430. vardef good.top primary z = save z_; pair z_;
  431.   (z_+(0,pen_top))t_=round((z+(0,pen_top))t_); z_ enddef;
  432. vardef good.bot primary z = save z_; pair z_;
  433.   (z_+(0,pen_bot))t_=round((z+(0,pen_bot))t_); z_ enddef;
  434.  
  435. vardef penpos@#(expr b,d) =
  436.  (x@#r-x@#l,y@#r-y@#l)=(b,0) rotated d;
  437.  x@#=.5(x@#l+x@#r); y@#=.5(y@#l+y@#r) enddef;
  438.  
  439. def penstroke text t =
  440.  forsuffixes e = l,r: path_.e:=t; endfor
  441.  if cycle path_.l: cyclestroke_
  442.  else: fill path_.l -- reverse path_.r -- cycle fi enddef;
  443. def cyclestroke_ =
  444.  begingroup interim turningcheck:=0;
  445.  addto pic_ contour path_.l.t_ withweight 1;
  446.  addto pic_ contour path_.r.t_ withweight _;
  447.  cull pic_ dropping origin withweight default_wt_;
  448.  addto_currentpicture also pic_;
  449.  pic_:=nullpicture endgroup enddef;
  450. path path_.l,path_.r;
  451.  
  452. message " macros for proof labels and rules,";
  453.  
  454. vardef makelabel@#(expr s,z) = % puts string s at point z
  455.  if known z: special lcode_@# & s;
  456.   numspecial xpart(z.t_); numspecial ypart(z.t_) fi enddef;
  457. string lcode_,lcode_.top,lcode_.lft,lcode_.rt,lcode_.bot,
  458.   lcode_.top.nodot,lcode_.lft.nodot,lcode_.rt.nodot,lcode_.bot.nodot;
  459. lcode_.top=" 1"; lcode_.lft=" 2"; lcode_.rt=" 3"; lcode_.bot=" 4";
  460. lcode_=" 0"; % change to " /" to avoid listing in overflow column
  461. lcode_.top.nodot=" 5"; lcode_.lft.nodot=" 6";
  462. lcode_.rt.nodot=" 7"; lcode_.bot.nodot=" 8";
  463.  
  464. vardef labels@#(text t) =
  465.  if proofing>1: forsuffixes $=t:
  466.   makelabel@#(str$,z$); endfor
  467.  fi enddef;
  468. vardef penlabels@#(text t) =
  469.  if proofing>1: forsuffixes $$=l,,r: forsuffixes $=t:
  470.   makelabel@#(str$.$$,z$.$$); endfor endfor
  471.  fi enddef;
  472.  
  473. def range expr x = numtok[x] enddef;
  474. def numtok suffix x=x enddef;
  475. tertiarydef m thru n =
  476.  m for x=m+1 step 1 until n: , numtok[x] endfor enddef;
  477.  
  478. def proofrule(expr w,z) =
  479.  special "rule"; numspecial xpart w; numspecial ypart w;
  480.  numspecial xpart z; numspecial ypart z enddef;
  481. def screenrule(expr w,z) =
  482.  addto currentpicture doublepath w--z withpen rulepen enddef;
  483. pen rulepen; rulepen = pensquare scaled 2;
  484.  
  485. def makegrid(text xlist,ylist) =
  486.  xmin_ := min(xlist); xmax_ := max(xlist);
  487.  ymin_ := min(ylist); ymax_ := max(ylist);
  488.  for x=xlist: proofrule((x,ymin_), (x,ymax_)); endfor
  489.  for y=ylist: proofrule((xmin_,y), (xmax_,y)); endfor
  490.  enddef;
  491.  
  492. vardef titlefont suffix $ = special "titlefont "&str$ enddef;
  493. vardef labelfont suffix $ = special "labelfont "&str$ enddef;
  494. vardef grayfont suffix $ = special "grayfont "&str$ enddef;
  495. vardef slantfont suffix $ = special "slantfont "&str$ enddef;
  496. def proofoffset primary z = % shifts proof output by z
  497.  special "offset"; numspecial xpart z; numspecial ypart z enddef;
  498. vardef proofrulethickness expr x =
  499.  special "rulethickness"; numspecial x enddef;
  500.  
  501. message " macros for character and font administration,";
  502.  
  503. def beginchar(expr c,w_sharp,h_sharp,d_sharp) =
  504.  begingroup
  505.  charcode:=if known c: byte c else: 0 fi;
  506.  charwd:=w_sharp;      charht:=h_sharp;       chardp:=d_sharp;
  507.  w:=hround(charwd*hppp); h:=vround(charht*hppp); d:=vround(chardp*hppp);
  508.  charic:=0; clearxy; clearit; clearpen; scantokens extra_beginchar;
  509.  enddef;
  510.  
  511. def italcorr expr x_sharp = if x_sharp>0: charic:=x_sharp fi enddef;
  512.  
  513. def change_width =
  514.  w:=w if w>charwd*hppp:- else:+ fi 1 enddef;
  515.  
  516. def endchar =
  517.  scantokens extra_endchar;
  518.  if proofing>0: makebox(proofrule); fi
  519.  chardx:=w;     % desired width of the character in pixels
  520.  shipit;
  521.  if displaying>0: makebox(screenrule); showit; fi
  522.  endgroup enddef;
  523.  
  524. string extra_beginchar, extra_endchar;
  525. extra_beginchar=extra_endchar="";
  526.  
  527. def makebox(text r) =
  528.  for y=0,h.o_,-d.o_: r((0,y),(w,y)); endfor % horizontals
  529.  for x=0,w:   r((x,-d.o_),(x,h.o_)); endfor % verticals
  530.  if charic<>0: r((w+charic*hppp,h.o_),(w+charic*hppp,.5h.o_)); fi
  531.  enddef;
  532.  
  533. def maketicks(text r) =
  534.  for y=0,h.o_,-d.o_: r((0,y),(10,y)); r((w-10,y),(w,y)); endfor
  535.  for x=0,w: r((x,10-d.o_),(x,-d.o_)); r((x,h.o_-10),(x,h.o_)); endfor
  536.  if charic<>0: r((w+charic*hppp,h.o_-10),(w+charic*hppp,h.o_)); fi
  537.  enddef;
  538.  
  539. def font_size expr x = designsize:=x enddef;
  540. def font_slant expr x = fontdimen 1: x enddef;
  541. def font_normal_space expr x = fontdimen 2: x enddef;
  542. def font_normal_stretch expr x = fontdimen 3: x enddef;
  543. def font_normal_shrink expr x = fontdimen 4: x enddef;
  544. def font_x_height expr x = fontdimen 5: x enddef;
  545. def font_quad expr x = fontdimen 6: x enddef;
  546. def font_extra_space expr x = fontdimen 7: x enddef;
  547.  
  548. def font_identifier expr x = font_identifier_:=x enddef;
  549. def font_coding_scheme expr x = font_coding_scheme_:=x enddef;
  550. string font_identifier_, font_coding_scheme_;
  551. font_identifier_=font_coding_scheme_="UNSPECIFIED";
  552.  
  553. message "and a few last-minute items.";
  554.  
  555. vardef z@#=(x@#,y@#) enddef;
  556.  
  557. newinternal screen_rows, screen_cols, currentwindow;
  558. screen_rows:=400;     % these values should be corrected,
  559. screen_cols:=500;     % by reading in a separate file after PLAIN.MF
  560.  
  561. def openit = openwindow currentwindow
  562.  from origin to (screen_rows,screen_cols) at (-50,300) enddef;
  563. def showit = openit; let showit=showit_; showit enddef; % first time only
  564. def showit_ = display currentpicture inwindow currentwindow enddef;
  565.  
  566. def clearxy = save x,y enddef;
  567. def clearit = currentpicture:=nullpicture enddef;
  568. def shipit = shipout currentpicture enddef;
  569. def cullit = cull currentpicture dropping (-infinity,0) enddef;
  570.  
  571. def screenchars =     % endchar should `showit'
  572.  extra_endchar:=extra_endchar&"showit;" enddef;
  573. def screenstrokes =   % every stroke should `showit'
  574.  def addto_currentpicture text t=
  575.   addto currentpicture t; showit enddef; enddef;
  576. def imagerules =      % a box should be part of the character image
  577.  extra_beginchar:=extra_beginchar & "makebox(screenrule);" enddef;
  578. def gfcorners =       % `maketicks' should send rules to the GF file
  579.  extra_setup:=extra_setup & "let makebox=maketicks;proofing:=1;" enddef;
  580. def nodisplays =      % endchar shouldn't `showit'
  581.  extra_setup:=extra_setup & "displaying:=0;" enddef;
  582. def notransforms =    % currenttransform should not be used
  583.  let t_ = \ enddef;
  584.  
  585. let bye = end; outer end,bye;
  586.  
  587. clear_pen_memory;     % initialize the `savepen' mechanism
  588. mode_setup;           % establish proof mode as the default
  589. numeric mode,mag;     % but leave mode and mag undefined
  590.